package model;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.logging.Logger;
import model.exception.MisformattedRowException;
import model.exception.UnsupportedFileTypeException;


/**
 * Class that stores all data we loaded from TSV/CSV files.
 * acts as in-memory database
 *
 * @author Zach Michaelov
 *         Modified by Amay Jhaveri
 */
public class DataTable implements DataSource {

    // the internal representation
    private static final String TAB_REGEX = "\t";
    private static final String NEW_LINE_REGEX = "\n";
    private List<DataColumn> myColumns;
    private int myCols;

    /**
     * The constructor for the DataTable.
     */
    public DataTable () {
        this.myColumns = new ArrayList<DataColumn>();
    }

    @SuppressWarnings("finally")
    @Override
    public void loadDataFromFile (File dataFile) {

            FileParser fileParser = FileParserFactory.fromFile(dataFile);

            if (fileParser.hasHeaders()) {
                initializeTable(fileParser.getHeaders());
            }
            // while the fileparser
            while (fileParser.hasNexRow()) {
                try {
                    addRow(fileParser.getNextRow());
                } catch (MisformattedRowException e) {
                    Logger.getLogger(this.getClass().toString()).info("Skipped Bad Row");
                }
                finally{
                    continue;
                }


            }
            // we are done with the FileParser
            fileParser.close();
    }

    @Override
    public List<String> getColumnNames () {
        List<String> names = new ArrayList<String>();
        for (DataColumn col : myColumns) {
            names.add(col.getName());
        }
        return names;
    }

    @Override
    public List<String> getColumn (String columnName) {
        for (DataColumn col : myColumns) {
            if (col.getName().equals(columnName)) { return col.getData(); }
        }
        return null;
    }

    @Override
    public String toString () {
        StringBuilder sb = new StringBuilder();
        for (DataColumn d : myColumns) {
            sb.append(d.getName() + TAB_REGEX);
        }

        sb.append(NEW_LINE_REGEX);
        List<Iterator<String>> it = new ArrayList<Iterator<String>>();
        for (DataColumn col : myColumns) {
            List<String> stringData = col.getData();
            it.add(stringData.listIterator());
        }

        for (DataColumn col : myColumns) {
            for (String s : col.getData()) {
                sb.append(s + TAB_REGEX);
            }
            sb.append(NEW_LINE_REGEX);
        }

        return sb.toString();
    }

    /**
     * @param rowVals - The row to be added to the table
     */
    private void addRow(List<String> rowVals) {
        if (rowVals.size() != myCols) {
            // pass in the row that caused the exception
            throw new MisformattedRowException(
                    "Number of row elements does not match number of columns",
                    rowVals.toString());
        }
        for (int i = 0; i < rowVals.size(); i++) {
            String cell = rowVals.get(i).trim();
            myColumns.get(i).addData(cell);
        }

    }

    /**
     * initialize our data table with the column headers extracted by our FileParser
     * @param headers
     */
    private void initializeTable (List<String> headers) {
        myCols = headers.size();
        for (String headerName : headers) {
            myColumns.add(new DataColumn(headerName.trim()));
        }
    }
}
